package com.info.dpunified.defects;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

import com.info.dpunified.common.MappingConstants;
import com.info.dpunified.common.utils.DPUUnifiedConstants;
import com.info.dpunified.common.utils.SQLConstants;
import com.info.dpunified.common.utils.StringUtils;
import com.info.dpunified.defects.dataaccess.dao.DefectsSelectorDAO;
import com.info.dpunified.defects.transfer.DefectsSelection;

public class DefectsSelector implements DPUUnifiedConstants,SQLConstants{
	
		
	/**
	 * This DAO class fetches the filter criteria needed by the user to view
	 * defects submitted
	 */
	private DefectsSelectorDAO defectsSelectorDAO;
	
	/**
	 * This map enables display of various categories a user can filter 
	 * the defects submitted
	 */
	private HashMap<String, ArrayList<String>> filterCriteriaMap;
	
	/**
	 * @return the filterCriteriaMap
	 */
	public HashMap<String, ArrayList<String>> getFilterCriteriaMap() {
		return filterCriteriaMap;
	}

	/**
	 * @param filterCriteriaMap the filterCriteriaMap to set
	 */
	public void setFilterCriteriaMap(HashMap<String, ArrayList<String>> filterCriteriaMap) {
		this.filterCriteriaMap = filterCriteriaMap;
	}

	/**
	 * @return the defectsSelectorDAO
	 */
	public DefectsSelectorDAO getDefectsSelectorDAO() {
		return defectsSelectorDAO;
	}

	/**
	 * @param defectsSelectorDAO the defectsSelectorDAO to set
	 */
	public void setDefectsSelectorDAO(DefectsSelectorDAO defectsSelectorDAO) {
		this.defectsSelectorDAO = defectsSelectorDAO;
	}

	public DefectsSelector()
	{
		XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-context.xml")) ;
		defectsSelectorDAO =(DefectsSelectorDAO) beanFactory.getBean("defectsSelectorDAO");
	}
	
	public List<DefectsSelection> fetchDefectsReport(DefectsSelection defectsSelection)
	{
	
		String query = this.prepareReportsQuery(defectsSelection);
		
		return defectsSelectorDAO.fetchDefects(query);
	}
	
	/**
	 * This method takes in the username and populates a filter search criteria hashmap
	 * @param userName
	 */
	public void populateFilterCriteria()
	{
		List<DefectsSelection> filterCriteria = defectsSelectorDAO.fetchCriteria();
		
		this.filterCriteriaMap = new HashMap<String, ArrayList<String>>();
		
		/**
		 * Preinitialise the map
		 */
		ArrayList<String> yearList = new ArrayList<String>();
		ArrayList<String> monthList = new ArrayList<String>();
		ArrayList<String> projectCodeList = new ArrayList<String>();
		ArrayList<String> impactList = new ArrayList<String>();
		ArrayList<String> priorityList = new ArrayList<String>();
		ArrayList<String> severityList = new ArrayList<String>();
		ArrayList<String> statusList = new ArrayList<String>();
		ArrayList<String> typeList = new ArrayList<String>();
		
		
		yearList.add(ALL);
		this.filterCriteriaMap.put(YEAR, yearList);
		monthList.add(ALL);
		this.filterCriteriaMap.put(MONTH, monthList);
		projectCodeList.add(ALL);
		this.filterCriteriaMap.put(PROJECTCODE, projectCodeList);
		impactList.add(ALL);
		this.filterCriteriaMap.put(DEFECTIMPACT, impactList);
		priorityList.add(ALL);
		this.filterCriteriaMap.put(DEFECTPRIORITY, priorityList);
		severityList.add(ALL);
		this.filterCriteriaMap.put(DEFECTSEVERITY, severityList);
		statusList.add(ALL);
		this.filterCriteriaMap.put(DEFECTSTATUS, statusList);
		typeList.add(ALL);
		this.filterCriteriaMap.put(DEFECTTYPE, typeList);
				
		
		for(DefectsSelection defectsSelection : filterCriteria)
		{
			yearList =  this.filterCriteriaMap.get(YEAR);
			if(!yearList.contains(defectsSelection.getYear()))
			{
				yearList.add(defectsSelection.getYear());
				this.filterCriteriaMap.put(YEAR, yearList);
			}
			
			monthList =  this.filterCriteriaMap.get(MONTH);
			if(!monthList.contains(defectsSelection.getMonth()))
			{
				monthList.add(defectsSelection.getMonth());
				this.filterCriteriaMap.put(MONTH, monthList);
			}
			
			projectCodeList =  this.filterCriteriaMap.get(PROJECTCODE);
			if(!projectCodeList.contains(defectsSelection.getProjectCode()))
			{
				projectCodeList.add(defectsSelection.getProjectCode());
				this.filterCriteriaMap.put(PROJECTCODE, projectCodeList);
			}
			
			
			impactList =  this.filterCriteriaMap.get(DEFECTIMPACT);
			if(!impactList.contains(defectsSelection.getImpact()))
			{
				impactList.add(defectsSelection.getImpact());
				this.filterCriteriaMap.put(DEFECTIMPACT, impactList);
			}
			
			priorityList =  this.filterCriteriaMap.get(DEFECTPRIORITY);
			if(!priorityList.contains(defectsSelection.getPriority()))
			{
				priorityList.add(defectsSelection.getPriority());
				this.filterCriteriaMap.put(DEFECTPRIORITY, priorityList);
			}
			
			severityList =  this.filterCriteriaMap.get(DEFECTSEVERITY);
			if(!severityList.contains(defectsSelection.getSeverity()))
			{
				severityList.add(defectsSelection.getSeverity());
				this.filterCriteriaMap.put(DEFECTSEVERITY, severityList);
			}
			
			statusList =  this.filterCriteriaMap.get(DEFECTSTATUS);
			if(!statusList.contains(defectsSelection.getStatus()))
			{
				statusList.add(defectsSelection.getStatus());
				this.filterCriteriaMap.put(DEFECTSTATUS, statusList);
			}
			
			typeList =  this.filterCriteriaMap.get(DEFECTTYPE);
			if(!typeList.contains(defectsSelection.getType()))
			{
				typeList.add(defectsSelection.getType());
				this.filterCriteriaMap.put(DEFECTTYPE, typeList);
			}
			
		}
		
		
	}
	
	/**
	 * This method prepares the SQL query required to fetch the details of defects based on user filter criteria
	 * @param defectsSelection
	 * @return sl query for defects report
	 */
	private String prepareReportsQuery(DefectsSelection defectsSelection)
	{
		StringBuffer reportQuery = new StringBuffer();
		String criterion = "";
		
		reportQuery.append("SELECT DISTINCT MONTH, YEAR, A.PROJECTCODE PROJECTCODE,A.DEFECTTYPE " +
				"DEFECTTYPE,A.DEFECTSTATUS DEFECTSTATUS, A.DEFECTSEVERITY DEFECTSEVERITY," +
				"A.DEFECTPRIORITY DEFECTPRIORITY, A.DEFECTIMPACT DEFECTIMPACT FROM DPURADARDEFECT A WHERE ");
		
		/**
		 * Filter against year
		 */
		if(!ALL.equals(defectsSelection.getYear()))
		{
			reportQuery.append("YEAR = ");
			reportQuery.append(defectsSelection.getYear());
			reportQuery.append(AND);
		}
		
		/**
		 * Filter against month
		 */
		if(!ALL.equals(defectsSelection.getMonth()))
		{
			reportQuery.append("MONTH = ");
			reportQuery.append(MappingConstants.getMonthValueMap().get(defectsSelection.getMonth()));
			reportQuery.append(AND);
		}
				
		
		/**
		 * Filter against projectCode
		 */
		reportQuery.append("PROJECTCODE LIKE ");
		criterion = ALL.equals(defectsSelection.getProjectCode()) ? MATCH_FULL : defectsSelection.getProjectCode();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(AND);
		
		/**
		 * Filter against defectType
		 */
		reportQuery.append("DEFECTTYPE LIKE ");
		criterion = ALL.equals(defectsSelection.getType()) ? MATCH_FULL : defectsSelection.getType();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(AND);
		/**
		 * Filter against defectStatus
		 */
		reportQuery.append("DEFECTSTATUS LIKE ");
		criterion = ALL.equals(defectsSelection.getStatus()) ? MATCH_FULL : defectsSelection.getStatus();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(AND);
		/**
		 * Filter against defectSeverity
		 */
		reportQuery.append("DEFECTSEVERITY LIKE ");
		criterion = ALL.equals(defectsSelection.getSeverity()) ? MATCH_FULL : defectsSelection.getSeverity();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(AND);
		/**
		 * Filter against defectPriority
		 */
		reportQuery.append("DEFECTPRIORITY LIKE ");
		criterion = ALL.equals(defectsSelection.getPriority()) ? MATCH_FULL : defectsSelection.getPriority();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(AND);
		/**
		 * Filter against defectImpact
		 */
		reportQuery.append("DEFECTIMPACT LIKE ");
		criterion = ALL.equals(defectsSelection.getImpact()) ? MATCH_FULL : defectsSelection.getImpact();
		reportQuery.append(StringUtils.quotes(criterion));
		
		reportQuery.append(" ORDER BY 1,2,3,4,5,6,7,8");
		return reportQuery.toString();

	}
	
}
